/**
 * 项目名：	Rumba Plan
 * 
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2006，所有权利保留。
 * 
 * 文件名：	BackProcessPool.java
 * 模块说明：	
 * 修改历史：
 * 2006-10-27 - lxm - 创建。
 */
package com.hd123.rumba.runtime.backprocess;

import java.util.ArrayList;
import java.util.List;

import com.hd123.rumba.exception.BusinessException;

/**
 * 后台处理过程池<br>
 * 
 * 这是一个Singleton。
 * 
 * @author lxm
 * 
 */
public class BackProcessPool extends Thread {

  private static BackProcessPool instance = null;
  private List<BackProcessRecord> processRecords;

  public BackProcessPool() {
    super();
    this.setDaemon(true);
    processRecords = new ArrayList();
  }

  public static BackProcessPool getInstance() {
    if (instance == null) {
      instance = new BackProcessPool();
      instance.start();
    }
    return instance;
  }

  public void run() {
    try {
      // 每间隔1分钟将已经中断的线程从processes中删除。
      while (true) {
        for (int i = processRecords.size() - 1; i >= 0; i--)
          if (Thread.State.TERMINATED.equals(processRecords.get(i).getProcess().getState()))
            processRecords.remove(i);
        sleep(5000);
      }
    } catch (InterruptedException e) {
      BackProcessPool.instance = null;
    }
  }

  /**
   * 将指定的后台处理过程放入池中。
   * 
   * @param process
   *          指定的后台处理过程实例。
   * @throws BusinessException
   */
  public synchronized void put(BackProcess process) throws BusinessException {
    if (process == null)
      throw new BusinessException("必须的参数process不可为空。");
    if (fetchRecord(process.getClass(), process.getOwnerKeys()) != null)
      throw new BusinessException("当前已有相同关键字的处理过程正在执行，当前执行请求被禁止。[" + process.getClass() + ", "
          + process.getOwnerKeys().toString() + "]");

    BackProcessRecord record = new BackProcessRecord();
    record.setProcessClass(process.getClass());
    record.setOwnerKeys(process.getOwnerKeys());
    record.setProcess(process);
    
    ProgressStack progressStack = new ProgressStack();
    process.setProgressStack(progressStack);
    Progress progress = progressStack.pushNew(1);
    progress.setCaption(process.getCaption());
    
    processRecords.add(record);
  }

  /**
   * 释放指定的处理过程。
   * 
   * @param process
   *          指定被删除的处理过程。
   */
  public synchronized void release(BackProcess process) {
    if (process == null)
      return;

    for (int i = 0; i < processRecords.size(); i++)
      if (process.equals(processRecords.get(i).getProcess())) {
        processRecords.remove(i);
        break;
      }
  }

  /**
   * 获取后台处理的进度。
   * 
   * @param processClassName
   *          指定的后台处理过程类名。
   * @param ownerKeys
   *          指定所有者关键字。
   * @return 返回表示处理进度的进度栈对象，若不存在则返回null。
   * @throws BusinessException
   */
  public ProgressStack fetchProgress(String processClassName, String[] ownerKeys)
      throws BusinessException {
    BackProcessRecord record = fetchRecord(processClassName, ownerKeys);
    if (record != null && !Thread.State.TERMINATED.equals(record.getProcess().getState()))
      return record.getProcess().getProgressStack();
    else
      return null;
  }

  /**
   * 获取后台处理的进度。
   * 
   * @param processClass
   *          指定的后台处理过程类。
   * @param ownerKeys
   *          指定所有者关键字。
   * @return 返回表示处理进度的进度栈对象，若不存在则返回null。
   * @throws BusinessException
   */
  public ProgressStack fetchProgress(Class processClass, String[] ownerKeys) throws BusinessException {
    BackProcessRecord record = fetchRecord(processClass, ownerKeys);
    if (record != null && !Thread.State.TERMINATED.equals(record.getProcess().getState()))
      return record.getProcess().getProgressStack();
    else
      return null;
  }

  /**
   * 获取后台处理的进度。
   * 
   * @param processUuid
   *          指定的后台处理过程实例的标识。
   * @return 返回表示处理进度的进度栈对象，若不存在则返回null。
   * @throws BusinessException
   */
  public ProgressStack fetchProgress(String processUuid) throws BusinessException {
    BackProcessRecord record = fetchRecord(processUuid);
    if (record != null && !Thread.State.TERMINATED.equals(record.getProcess().getState()))
      return record.getProcess().getProgressStack();
    else
      return null;
  }

  /**
   * 查找后台处理过程对象。
   * 
   * @param processClassName
   *          指定的后台处理过程类名。
   * @param ownerKeys
   *          指定所有者关键字。
   * @return 返回找到的后台处理过程对象，若找不到返回null。
   * @throws BusinessException
   */
  public BackProcess fetchProcess(String processClassName, String[] ownerKeys)
      throws BusinessException {
    BackProcessRecord record = fetchRecord(processClassName, ownerKeys);
    if (record != null)
      return record.getProcess();
    else
      return null;
  }

  /**
   * 查找后台处理过程对象。
   * 
   * @param processClass
   *          指定的后台处理过程类。
   * @param ownerKeys
   *          指定所有者关键字。
   * @return 返回找到的后台处理过程对象，若找不到返回null。
   * @throws BusinessException
   */
  public BackProcess fetchProcess(Class processClass, String[] ownerKeys) throws BusinessException {
    BackProcessRecord record = fetchRecord(processClass, ownerKeys);
    if (record != null)
      return record.getProcess();
    else
      return null;
  }

  private BackProcessRecord fetchRecord(String processClassName, String[] ownerKeys)
      throws BusinessException {
    if (processClassName == null)
      throw new BusinessException("必须的参数processClassName不可为空。");
    if (ownerKeys == null)
      throw new BusinessException("必须的参数ownerKeys不可为空。");

    BackProcessRecord record = null;
    for (int i = 0; i < processRecords.size(); i++) {
      if (!processClassName.equals(processRecords.get(i).getProcessClass().getName()))
        continue;
      String[] keys = processRecords.get(i).getOwnerKeys();
      if (ownerKeys.length != keys.length)
        continue;
      boolean equal = true;
      for (int j = 0; j < ownerKeys.length; j++)
        if (!ownerKeys[j].equals(keys[j])) {
          equal = false;
          break;
        }
      if (!equal)
        continue;
      record = processRecords.get(i);
      break;
    }
    return record;
  }

  private BackProcessRecord fetchRecord(Class processClass, String[] ownerKeys)
      throws BusinessException {
    if (processClass == null)
      throw new BusinessException("必须的参数processClass不可为空。");
    if (ownerKeys == null)
      throw new BusinessException("必须的参数ownerKeys不可为空。");

    BackProcessRecord record = null;
    for (int i = 0; i < processRecords.size(); i++) {
      if (!processClass.equals(processRecords.get(i).getProcessClass()))
        continue;
      String[] ownerKeys2 = processRecords.get(i).getOwnerKeys();
      if (ownerKeys.length != ownerKeys2.length)
        continue;
      boolean same = true;
      for (int j = 0; j < ownerKeys.length; j++)
        if (!ownerKeys[j].equals(ownerKeys2[j])) {
          same = false;
          break;
        }
      if (!same)
        continue;
      record = processRecords.get(i);
      break;
    }
    return record;
  }

  private BackProcessRecord fetchRecord(String processUuid) throws BusinessException {
    if (processUuid == null)
      throw new BusinessException("必须的参数processUuid不可为空。");

    BackProcessRecord record = null;
    for (int i = 0; i < processRecords.size(); i++)
      if (processUuid.equals(processRecords.get(i).getProcess().getUuid())) {
        record = processRecords.get(i);
        break;
      }
    return record;
  }

  private class BackProcessRecord {
    private Class processClass;
    private String[] ownerKeys;
    private BackProcess process;

    public String[] getOwnerKeys() {
      return ownerKeys;
    }

    public void setOwnerKeys(String[] ownerKeys) {
      this.ownerKeys = ownerKeys;
    }

    public BackProcess getProcess() {
      return process;
    }

    public void setProcess(BackProcess process) {
      this.process = process;
    }

    public Class getProcessClass() {
      return processClass;
    }

    public void setProcessClass(Class processClass) {
      this.processClass = processClass;
    }
  }

}
